/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.jeff.springWebTestNG.io;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author winnie
 */
public class NioPlayer {
    static final Logger LOG = Logger.getLogger(NioPlayer.class.getName());
    private File tempFile = null;
    public NioPlayer() {
        
        try {
            tempFile = File.createTempFile("nioplayer", null);
            initTempFile(tempFile);
            tempFile.deleteOnExit();
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }
    
    private void initTempFile(File tempFile) {
        try {
            FileOutputStream fos = new FileOutputStream(tempFile);
            //Unicode is OSX default encodig
            fos.write("我爱你亲爱的姑娘，见到你我就慌张!".getBytes(/*Charset.forName("ISO-8859-1")*/));
            
            recycleCloseableResource(fos);
        } catch (FileNotFoundException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } 
        
    }
    
    public static void main(String[] args) {
//        new NioPlayer().playResetPosition();
//        new NioPlayer().playBufferForCopyStream();
        new NioPlayer().playAdvancedEncoder();
    }
    
    public void playBufferForCopyStream() {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        try {
            ReadableByteChannel readChannel = Channels.newChannel(new FileInputStream(tempFile));
            ByteArrayOutputStream out = new ByteArrayOutputStream(32*1024);
            WritableByteChannel writeChannel = Channels.newChannel(out);
            
            buffer.clear();
            while(readChannel.read(buffer) > 0 || buffer.position() != 0) {
                buffer.flip();
                writeChannel.write(buffer);
                buffer.compact(); //if write incompletely, and this make postion > 0
            }
            
            byte[] result = out.toByteArray();
            System.out.println(new String(result));
        } catch (FileNotFoundException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }
    
    public void playResetPosition() {
        StringReader source = null;
        try {
            source = new StringReader("abcdefg");
            for (int i = 0; i < 2; i++) {
                int intChar = source.read();
                char aChar = (char)intChar;
                System.out.print(aChar);
            }
    //        System.out.println(source.markSupported());
            System.out.print("\n");

            source.mark(Integer.MAX_VALUE);
            System.out.print((char)source.read());
            source.reset();
            System.out.print((char)source.read());
            source.reset();
            System.out.print((char)source.read());

            System.out.println();
        } catch (IOException e) {
            LOG.severe("IOException!");
        } finally {
            recycleCloseableResource(source);
        }
    }
    
    private void recycleCloseableResource(Object stream) {
        if (stream == null) return;
        
        try {
            System.out.println("Program Closing: " + stream.getClass());
            Method closeMethod = stream.getClass().getMethod("close", null);
            closeMethod.invoke(stream, null);
        } catch (NoSuchMethodException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }

    public void playAdvancedEncoder() {
        String input = "你abc好";
        Charset charset = Charset.forName("ISO-8859-1");
        CharsetEncoder encoder = charset.newEncoder();
        encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
        CharsetDecoder decoder = charset.newDecoder();
        CharBuffer cbuf = CharBuffer.allocate(32);
        cbuf.put(input).flip();
        
        try {
            ByteBuffer bbuf = encoder.encode(cbuf);
            CharBuffer cbufcbuf = decoder.decode(bbuf);
            System.out.println(cbufcbuf);//result should be "abc" only
        } catch (CharacterCodingException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }

}
